<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="Mb3Sz" id="Mb3Sz"><span data-lake-id="u09de5a56" id="u09de5a56">典型回答</span></h1>
  <p data-lake-id="u3e1be689" id="u3e1be689"><br></p>
  <p data-lake-id="u4321108c" id="u4321108c"><span data-lake-id="uf9930cd0" id="uf9930cd0">关于Tomcat的IO模型，不同的版本中是不太一样的，下面是一张Tomcat官网中各个历史重要版本所采用IO模型的介绍：</span></p>
  <p data-lake-id="ud32b2c5c" id="ud32b2c5c"><br></p>
  <p data-lake-id="ubda75bbd" id="ubda75bbd" style="text-align: center"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1690605161347-193f9771-970d-4b79-bc2e-d946ed9af782.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_25%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u6700d9fc" id="u6700d9fc"><br></p>
  <p data-lake-id="ud304a506" id="ud304a506"><span data-lake-id="u927524fb" id="u927524fb">综合来说就是Tomcat支持多种IO模型，包括了标准的BIO（Blocking I/O）、NIO（Non-Blocking I/O）、NIO2（即JDK 1.7中的AIO）和APR（Apache Portable Runtime）。</span></p>
  <p data-lake-id="udc6285b0" id="udc6285b0"><span data-lake-id="ucc824d0a" id="ucc824d0a">​</span><br></p>
  <ul list="uda80bcf3">
   <li fid="uc72029d5" data-lake-id="u3b891cf4" id="u3b891cf4" data-lake-index-type="true"><strong><span data-lake-id="u1e8b99d9" id="u1e8b99d9">BIO</span></strong><span data-lake-id="uf1920068" id="uf1920068">是最传统的线程模型，也称为阻塞I/O。在BIO模型中，每个客户端连接都由一个独立的线程处理。当有新的连接到来时，Tomcat会创建一个新的线程来处理请求。这意味着每个连接都需要一个独立的线程，当并发连接数较大时，会导致线程数急剧增加，占用大量系统资源，并且可能出现线程切换带来的开销。</span></li>
   <li fid="uc72029d5" data-lake-id="ub3f1ffec" id="ub3f1ffec" data-lake-index-type="true"><strong><span data-lake-id="u22f59fc1" id="u22f59fc1">NIO</span></strong><span data-lake-id="uea9ec4cc" id="uea9ec4cc">是Java的新I/O库（java.nio）的线程模型。在NIO模型中，通过使用Java NIO的选择器（Selector）机制，一个线程可以同时处理多个连接的请求。NIO模型相对于BIO模型来说，能够支持更多的并发连接，并且在连接数较大时对系统资源的消耗较少，但由于在应用层需要处理I/O事件，编程较为复杂。</span></li>
   <li fid="uc72029d5" data-lake-id="u5e29f6f9" id="u5e29f6f9" data-lake-index-type="true"><strong><span data-lake-id="uf3d1dd60" id="uf3d1dd60">NIO2</span></strong><span data-lake-id="u12b5049d" id="u12b5049d">是Java 7引入的进一步改进的NIO模型，也叫AIO。在NIO2中，Java提供了更多的异步I/O操作，包括异步文件I/O、异步套接字I/O等。这使得Tomcat能够更好地支持异步请求处理，提高了处理性能和效率。</span></li>
   <li fid="uc72029d5" data-lake-id="ub7449b65" id="ub7449b65" data-lake-index-type="true"><strong><span data-lake-id="ubbf0250b" id="ubbf0250b">APR</span></strong><span data-lake-id="u522eb53a" id="u522eb53a">是Apache软件基金会提供的一个库，它为应用程序提供了跨平台的抽象层，提供了高性能的本地I/O支持。在APR模型中，Tomcat利用本地操作系统的特性进行I/O操作，包括网络和文件I/O。APR模型在性能方面表现得非常出色，特别是在处理大量并发连接时，因为它直接利用底层操作系统的异步I/O能力。</span></li>
  </ul>
  <p data-lake-id="u0b20dda6" id="u0b20dda6"><span data-lake-id="uafd11c4a" id="uafd11c4a">​</span><br></p>
  <p data-lake-id="uae5ab7e0" id="uae5ab7e0"><span data-lake-id="u56e8317f" id="u56e8317f">​</span><br></p>
  <p data-lake-id="ufc60ee4b" id="ufc60ee4b"><span data-lake-id="ud8e949e4" id="ud8e949e4">我们可以在Tomcat启动的时候，可以通过log看到Connector使用的是哪一种运行模式：</span></p>
  <p data-lake-id="uc9192b0e" id="uc9192b0e"><span data-lake-id="u4d0cde8a" id="u4d0cde8a">​</span><br></p>
  <pre lang="java"><code>
Starting ProtocolHandler [“http-bio-8080”]
Starting ProtocolHandler [“http-nio-8080”]
Starting ProtocolHandler [“http-apr-8080”]
</code></pre>
  <p data-lake-id="ud2392937" id="ud2392937"><br></p>
  <h1 data-lake-id="xKXyB" id="xKXyB"><span data-lake-id="ue09598e3" id="ue09598e3">扩展知识</span></h1>
  <p data-lake-id="u4e708360" id="u4e708360"><br></p>
  <h2 data-lake-id="yzIcn" id="yzIcn"><span data-lake-id="ub58a5ce6" id="ub58a5ce6">如何切换</span></h2>
  <p data-lake-id="u628e1a6e" id="u628e1a6e"><br></p>
  <p data-lake-id="u1868f5e9" id="u1868f5e9"><span data-lake-id="u6858dd12" id="u6858dd12">切换Tomcat使用的I/O模型通常涉及配置Tomcat的连接器（Connector）。不同的I/O模型对应着不同的连接器实现。</span></p>
  <p data-lake-id="ud322a3f8" id="ud322a3f8"><span data-lake-id="u41c82f1a" id="u41c82f1a">​</span><br></p>
  <p data-lake-id="uccae5b4e" id="uccae5b4e"><span data-lake-id="u3004ef25" id="u3004ef25">在server.xml文件中，通过配置Connecter来选择不同的IO模型，如：</span></p>
  <p data-lake-id="u201c8ed9" id="u201c8ed9"><span data-lake-id="u28ed80ea" id="u28ed80ea">​</span><br></p>
  <pre lang="java"><code>
&lt;Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" /&gt;
</code></pre>
  <p data-lake-id="u6b647a9d" id="u6b647a9d"><span data-lake-id="u5cf626ed" id="u5cf626ed">​</span><br></p>
  <p data-lake-id="u98c446a7" id="u98c446a7"><span data-lake-id="u6f9ad13a" id="u6f9ad13a">这里的protocol就是可以修改来替换成其他的协议，即IO模型的地方。</span></p>
  <p data-lake-id="u815f600f" id="u815f600f"><span data-lake-id="u4db5a6a4" id="u4db5a6a4">​</span><br></p>
  <p data-lake-id="u0930ddce" id="u0930ddce"><span data-lake-id="uabc6c425" id="uabc6c425">各个IO模型对应的关系如下：</span></p>
  <p data-lake-id="u840184d6" id="u840184d6"><span data-lake-id="ud4655beb" id="ud4655beb">​</span><br></p>
  <ul list="ufb566a51">
   <li fid="udfce5879" data-lake-id="u59ac5bb5" id="u59ac5bb5" data-lake-index-type="true"><span data-lake-id="u031109e9" id="u031109e9">BIO模型：将</span><span data-lake-id="u918649fc" id="u918649fc">protocol</span><span data-lake-id="u19d52992" id="u19d52992">属性设置为</span><span data-lake-id="u42077210" id="u42077210">HTTP/1.1</span><span data-lake-id="u87ff3ae3" id="u87ff3ae3">（默认值），或者可以显式地设置为</span><span data-lake-id="u3b89ee03" id="u3b89ee03">org.apache.coyote.http11.Http11Protocol</span><span data-lake-id="u35421823" id="u35421823">。</span></li>
   <li fid="udfce5879" data-lake-id="ub09be43d" id="ub09be43d" data-lake-index-type="true"><span data-lake-id="u03513ed8" id="u03513ed8">NIO模型：将</span><span data-lake-id="u4f020a2d" id="u4f020a2d">protocol</span><span data-lake-id="uf9464dbb" id="uf9464dbb">属性设置为</span><span data-lake-id="u624f4432" id="u624f4432">org.apache.coyote.http11.Http11NioProtocol</span><span data-lake-id="u6f4aa5c5" id="u6f4aa5c5">。</span></li>
   <li fid="udfce5879" data-lake-id="ua509420a" id="ua509420a" data-lake-index-type="true"><span data-lake-id="uc1fd8da4" id="uc1fd8da4">NIO2模型：将</span><span data-lake-id="u51a359fb" id="u51a359fb">protocol</span><span data-lake-id="u812f44da" id="u812f44da">属性设置为</span><span data-lake-id="u07edf83d" id="u07edf83d">org.apache.coyote.http11.Http11Nio2Protocol</span><span data-lake-id="u64bcef10" id="u64bcef10">。</span></li>
   <li fid="udfce5879" data-lake-id="ud705a0e5" id="ud705a0e5" data-lake-index-type="true"><span data-lake-id="uebb683cc" id="uebb683cc">APR模型：将protocol属性设置为org.apache.coyote.http11.Http11AprProtocol。</span></li>
  </ul>
  <p data-lake-id="ua0c70c87" id="ua0c70c87"><span data-lake-id="u9a42a85e" id="u9a42a85e">​</span><br></p>
  <p data-lake-id="ueee4a7a6" id="ueee4a7a6"><span data-lake-id="u8e6cb7f9" id="u8e6cb7f9">但是记得修改后需要重启tomcat才会生效。而且需要注意，Tomcat的不同版本可能支持不同的I/O模型，因此请根据您使用的Tomcat版本进行相应的配置。</span></p>
  <p data-lake-id="ucd2859ab" id="ucd2859ab"><span data-lake-id="ub8903b18" id="ub8903b18">​</span><br></p>
  <p data-lake-id="ufa9e8503" id="ufa9e8503"><span data-lake-id="u410f0e61" id="u410f0e61">一般来说，建议使用NIO或者NIO2就行了，对于涉及大量I/O操作的应用，例如Web服务、聊天应用或在线游戏等，NIO或NIO2模型都挺合适。</span></p>
  <p data-lake-id="u68751d1f" id="u68751d1f"><span data-lake-id="ufccca73a" id="ufccca73a">​</span><br></p>
  <p data-lake-id="uaba00dc1" id="uaba00dc1"><span data-lake-id="u20b7da3f" id="u20b7da3f">如果对性能要求非常高，可以考虑使用APR模型，但需要安装和配置APR库，有一定的成本。</span></p>
 </body>
</html>